using System;
using System.Collections;

namespace csammisrun.OscarLib.Utility
{
	/// <summary>
	/// Provides static methods for processing messages in SNAC family 0x0003 -- buddy list management service
	/// </summary>
	internal static class SNAC03
	{
    public const int PARAMETER_MAXBUDDIES = 0x0001;
		public const int PARAMETER_MAXWATCHERS = 0x0002;
		public const int PARAMETER_MAXNOTIFICATIONS = 0x0003;

		/// <summary>
		/// Sends a request for parameter information -- SNAC(03,02)
		/// </summary>
		/// <param name="sess">A <see cref="Session"/> object</param>
		public static void RequestParametersList(Session sess)
		{
			SNACHeader sh = new SNACHeader();
			sh.FamilyServiceID = (ushort)SNACFamily.BuddyListManagementService;
			sh.FamilySubtypeID = (ushort)BuddyListManagementService.LimitationsParamsRequest;
			sh.Flags = 0x0000;
			sh.RequestID = sess.GetNextRequestID();

			DataPacket dp = Marshal.BuildDataPacket(sess, sh, null);
			SNACFunctions.BuildFLAP(dp);
		}

		/// <summary>
		/// Processes the parameter information sent by the server -- SNAC(03,03)
		/// </summary>
		/// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(03,03)</param>
		public static void ProcessParametersList(DataPacket dp)
		{
			byte[] SNACData = dp.Data;

			int index = 0;
			ushort max_buddylist_size = 0;
			ushort max_watcherlist_entries = 0;
			ushort max_online_notifications = 0;

			while(index < SNACData.Length)
			{
				ushort key = Marshal.ByteArrayToUshort(SNACData, ref index);
				ushort keylength = Marshal.ByteArrayToUshort(SNACData, ref index);
				switch(key)
				{
					case PARAMETER_MAXBUDDIES:	// Max number of buddy list entries
						max_buddylist_size = Marshal.ByteArrayToUshort(SNACData, ref index);
						break;
					case PARAMETER_MAXWATCHERS:	// Max number of watcher list entries
						max_watcherlist_entries = Marshal.ByteArrayToUshort(SNACData, ref index);
						break;
					case PARAMETER_MAXNOTIFICATIONS:	// Max online notifications (?)
						max_online_notifications = Marshal.ByteArrayToUshort(SNACData, ref index);
						break;
					default:
						index += keylength;
						break;
				}
			}

			// Do something with these capabilities
			dp.ParentSession.ParameterSetArrived();
		}

		/// <summary>
		/// (Obsolete) Sends a request for a list of watchers -- SNAC(03,06)
		/// </summary>
		/// <param name="sess">A <see cref="Session"/> object</param>
		/// <remarks>
		/// <para>A "watcher" is a remote user who has this user on their contact list.</para>
		/// <para>This function is no longer supported by the AOL OSCAR servers.</para>
		/// </remarks>
		public static void RequestWatcherList(Session sess)
		{
			SNACHeader sh = new SNACHeader();
			sh.FamilyServiceID = (ushort)SNACFamily.BuddyListManagementService;
			sh.FamilySubtypeID = (ushort)BuddyListManagementService.WatcherListRequest;
			sh.Flags = 0x0000;
			sh.RequestID = sess.GetNextRequestID();

			DataPacket dp = Marshal.BuildDataPacket(sess, sh, null);
			SNACFunctions.BuildFLAP(dp);
		}

		/// <summary>
		/// Processes a list of watchers sent by the server -- SNAC(03,07)
		/// </summary>
		/// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(03,07) </param>
		public static void ProcessWatcherList(DataPacket dp)
		{
			byte[] SNACData = dp.Data;

			int index = 0;
			ArrayList list = new ArrayList();

			while(index < SNACData.Length)
			{
				byte strlen = SNACData[index++];
        list.Add(Marshal.ByteArrayToString(SNACData, ref index, strlen, Marshal.ASCII));
			}

			string[] watchers = new string[list.Count];
			for(index = 0; index < list.Count; index++)
			{
				list[index] = watchers[index];
			}

			// This SNAC does not work anymore, so there is no user event for it
		}

		/// <summary>
		/// Processes a user status notification sent by the server -- SNAC(03,0B)
		/// </summary>
		/// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(03,0B)</param>
		public static void ProcessOnlineNotification(DataPacket dp)
		{
			byte[] SNACData = dp.Data;

			int index = 0;
			bool valid = false;
			while(index < SNACData.Length)
			{
				UserInfo ui = Marshal.GetUserinfoBlock(SNACData, ref index, ref valid);
				if(valid)
				{
					dp.ParentSession.OnUserStatusReceived(ui);
				}
			}
		}

		/// <summary>
		/// Processes a user status notification sent by the server -- SNAC(03,0C)
		/// </summary>
		/// <param name="dp">A <see cref="DataPacket"/> object with a buffer containing SNAC(03,0C)</param>
		public static void ProcessOfflineNotification(DataPacket dp)
		{
			byte[] SNACData = dp.Data;

			int index = 0;
			bool valid = false;
			while(index < SNACData.Length)
			{
				UserInfo ui = Marshal.GetUserinfoBlock(SNACData, ref index, ref valid);
				if(valid)
				{
					dp.ParentSession.OnUserOffline(ui);
				}
			}
		}
	}
}
